import express from 'express';
import { prisma } from '../app';
import { asyncHandler, createError } from '../middleware/errorHandler';
import { authenticateToken, AuthRequest } from '../middleware/auth';

const router = express.Router();

// Get calendar events for a specific month
router.get('/events', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const userId = req.user!.id;
  const { year, month } = req.query;

  if (!year || !month) {
    throw createError('Year and month parameters are required', 400);
  }

  const targetYear = parseInt(year as string);
  const targetMonth = parseInt(month as string);

  if (isNaN(targetYear) || isNaN(targetMonth) || targetMonth < 1 || targetMonth > 12) {
    throw createError('Invalid year or month parameter', 400);
  }

  const startDate = new Date(targetYear, targetMonth - 1, 1);
  const endDate = new Date(targetYear, targetMonth, 0, 23, 59, 59, 999);

  const events = await prisma.calendarEvent.findMany({
    where: {
      userId,
      date: {
        gte: startDate,
        lte: endDate
      }
    },
    orderBy: [
      { date: 'asc' },
      { time: 'asc' }
    ]
  });

  res.json({
    success: true,
    data: { events }
  });
}));

// Get events for a specific date
router.get('/events/:date', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const userId = req.user!.id;
  const { date } = req.params;

  const targetDate = new Date(date);
  if (isNaN(targetDate.getTime())) {
    throw createError('Invalid date format', 400);
  }

  const startOfDay = new Date(targetDate);
  startOfDay.setHours(0, 0, 0, 0);
  
  const endOfDay = new Date(targetDate);
  endOfDay.setHours(23, 59, 59, 999);

  const events = await prisma.calendarEvent.findMany({
    where: {
      userId,
      date: {
        gte: startOfDay,
        lte: endOfDay
      }
    },
    orderBy: { time: 'asc' }
  });

  res.json({
    success: true,
    data: { events }
  });
}));

// Create a new calendar event
router.post('/events', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const userId = req.user!.id;
  const { title, date, time, description, color } = req.body;

  if (!title || !date) {
    throw createError('Title and date are required', 400);
  }

  if (title.length < 1 || title.length > 255) {
    throw createError('Title must be between 1 and 255 characters', 400);
  }

  const eventDate = new Date(date);
  if (isNaN(eventDate.getTime())) {
    throw createError('Invalid date format', 400);
  }

  let eventTime = null;
  if (time) {
    // Validate time format (HH:MM)
    const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/;
    if (!timeRegex.test(time)) {
      throw createError('Invalid time format. Use HH:MM format', 400);
    }
    eventTime = time;
  }

  const event = await prisma.calendarEvent.create({
    data: {
      title,
      date: eventDate,
      time: eventTime,
      description: description || null,
      color: color || '#3b82f6', // Default blue color
      userId
    }
  });

  res.status(201).json({
    success: true,
    message: 'Calendar event created successfully',
    data: { event }
  });
}));

// Update a calendar event
router.put('/events/:id', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const eventId = parseInt(req.params.id);
  const userId = req.user!.id;
  const { title, date, time, description, color } = req.body;

  if (isNaN(eventId)) {
    throw createError('Invalid event ID', 400);
  }

  // Check if event exists and belongs to user
  const existingEvent = await prisma.calendarEvent.findFirst({
    where: {
      id: eventId,
      userId
    }
  });

  if (!existingEvent) {
    throw createError('Calendar event not found', 404);
  }

  const updateData: any = {};

  if (title !== undefined) {
    if (!title || title.length < 1 || title.length > 255) {
      throw createError('Title must be between 1 and 255 characters', 400);
    }
    updateData.title = title;
  }

  if (date !== undefined) {
    const eventDate = new Date(date);
    if (isNaN(eventDate.getTime())) {
      throw createError('Invalid date format', 400);
    }
    updateData.date = eventDate;
  }

  if (time !== undefined) {
    if (time) {
      const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/;
      if (!timeRegex.test(time)) {
        throw createError('Invalid time format. Use HH:MM format', 400);
      }
      updateData.time = time;
    } else {
      updateData.time = null;
    }
  }

  if (description !== undefined) {
    updateData.description = description || null;
  }

  if (color !== undefined) {
    updateData.color = color || '#3b82f6';
  }

  const event = await prisma.calendarEvent.update({
    where: { id: eventId },
    data: updateData
  });

  res.json({
    success: true,
    message: 'Calendar event updated successfully',
    data: { event }
  });
}));

// Delete a calendar event
router.delete('/events/:id', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const eventId = parseInt(req.params.id);
  const userId = req.user!.id;

  if (isNaN(eventId)) {
    throw createError('Invalid event ID', 400);
  }

  // Check if event exists and belongs to user
  const existingEvent = await prisma.calendarEvent.findFirst({
    where: {
      id: eventId,
      userId
    }
  });

  if (!existingEvent) {
    throw createError('Calendar event not found', 404);
  }

  await prisma.calendarEvent.delete({
    where: { id: eventId }
  });

  res.json({
    success: true,
    message: 'Calendar event deleted successfully'
  });
}));

// Get upcoming events (next 7 days)
router.get('/upcoming', authenticateToken, asyncHandler(async (req: AuthRequest, res) => {
  const userId = req.user!.id;
  const { days = 7 } = req.query;

  const daysNum = parseInt(days as string);
  if (isNaN(daysNum) || daysNum < 1 || daysNum > 30) {
    throw createError('Days must be between 1 and 30', 400);
  }

  const today = new Date();
  today.setHours(0, 0, 0, 0);
  
  const futureDate = new Date(today);
  futureDate.setDate(today.getDate() + daysNum);
  futureDate.setHours(23, 59, 59, 999);

  const events = await prisma.calendarEvent.findMany({
    where: {
      userId,
      date: {
        gte: today,
        lte: futureDate
      }
    },
    orderBy: [
      { date: 'asc' },
      { time: 'asc' }
    ]
  });

  res.json({
    success: true,
    data: { events }
  });
}));

export default router;